﻿using AntdUI;
using Microsoft.Identity.Client;
using System.IO;
using System.Reflection;
using System.Security.Principal;
using System.Windows.Forms;
using WenAntdUI.Controls;
using WenAntdUI.Helps;
using WenAntdUI.Services;

namespace WenAntdUI.Forms;

/// <summary>
/// 默认启动首页窗口
/// </summary>
public class SysDefaultForm : Window
{
    private readonly TabHeader tabHeader;
    private readonly Menu menu1;
    private string title = "";
    private PageItemCollection? _items;
    private AntdUI.Panel Page;
    private readonly IdentityService identity;
    private readonly UserInfo userInfo;
    /// <summary>
    /// 页面选项列表
    /// </summary>
    public PageItemCollection Items => _items ??= new PageItemCollection(this);

    public SysDefaultForm(IdentityService identity, MenuService menu)
    {
        this.identity = identity;
        this.StartPosition = FormStartPosition.CenterScreen;
        this.Size = new Size(1280, 790);


        tabHeader = new TabHeader()
        {
            Dock = DockStyle.Top,
            Height = 35,
            ShowButton = true,
            ShowIcon = true,
            //DividerShow = true,
            //DividerMargin = 3,
            BackColor = Color.Transparent,
            DragSort = true,
        };
        this.tabHeader.Text = title = VersionHelp.GetAppNameVersion();

        var spli = new AntdUI.Splitter()
        {
            Width = this.Width,
            Dock = DockStyle.Fill,
            FixedPanel = FixedPanel.Panel1,
            SplitterDistance =  AppConfig.Config.IsMenuCollapsed ? (int)(52 * AntdUI.Config.Dpi) : AppConfig.Config.MenuSplitterDistance,
            BackColor = Color.Transparent,
        };


        var panelMenu = new AntdUI.Panel()
        {
            Dock = DockStyle.Fill,
            Width = 400,
            BackColor = Color.Transparent,
        };

        var inputMenuSearch = new Input()
        {
            Dock = DockStyle.Fill,
            PlaceholderText = "搜索菜单",
            PrefixSvg = "SearchOutlined",
            BackColor = Color.Transparent,
        };

        //菜单顶部功能
        var panelMenuTop = new AntdUI.Panel()
        {
            Dock = DockStyle.Top,
            Height = 40,
            BackColor = Color.Transparent,
        };


        #region 添加菜单列表组件

        menu1 = new Menu()
        {
            AutoCollapse = true,
            Dock = DockStyle.Fill,
            Indent = true,
        };

        #endregion


        #region 菜单收缩/展开
        //打开收缩菜单
        var btnMenuCollapsed = new AntdUI.Button()
        {
            Dock = DockStyle.Left,
            IconSvg = "MenuOutlined",
            Width = 40
        };

        btnMenuCollapsed.Click += (s, e) =>
        {
            if (!menu1.Collapsed)
            {
                //MenuCollapsedAll(null);
                inputMenuSearch.Visible = false;
                menu1.Collapsed = true;
                spli.SplitterDistance = (int)((40 + 12) * AntdUI.Config.Dpi);
            }
            else
            {
                inputMenuSearch.Visible = true;
                menu1.Collapsed = false;
                spli.SplitterDistance = (int)(210 * AntdUI.Config.Dpi);
            }
        };

        #endregion


        #region 菜单搜索输入框

        DateTime searchTextChangedTime = DateTime.Now;
        bool searchFinished = true;
        int searchDelayMs = 500;    // 延时搜索（毫秒）

        System.Windows.Forms.Timer timerMenuSearch = new() { Interval = 10 };

        timerMenuSearch.Tick += (s, e) =>
        {
            if ((DateTime.Now - searchTextChangedTime).TotalMilliseconds > searchDelayMs && !searchFinished)
            {
                //MenuSearch(null);
                //if (inputMenuSearch.Text == "") MenuCollapsedAll(null);
                searchFinished = true;
                timerMenuSearch.Stop();
            }
        };

        timerMenuSearch.Start();

        // 输入框文本变更时触发菜单搜索
        inputMenuSearch.TextChanged += (s, e) =>
        {
            searchTextChangedTime = DateTime.Now;
            searchFinished = false;
            timerMenuSearch.Start();
        };

        #endregion


        #region 右键菜单

        AntdUI.IContextMenuStripItem[] cMenu1 = [
            new AntdUI.ContextMenuStripItem( "全部折叠")
                {
                    IconSvg = "MenuFoldOutlined",
                    Tag = "CollapseAll",
                },
                new AntdUI.ContextMenuStripItem( "全部展开")
                {
                    IconSvg = "MenuUnfoldOutlined",
                    Tag = "ExpandAll",
                },
            ];

        menu1.MouseClick += (s, e) =>
        {
            if (e.Button == MouseButtons.Right)
            {
                AntdUI.ContextMenuStrip.open(this, it =>
                {
                    switch (it.Tag)
                    {
                        case "CollapseAll":
                            MenuCollapsedAll(null);
                            break;
                        case "ExpandAll":
                            MenuExpandAll(null);
                            break;
                    }
                }, cMenu1);
            }
        };

        #endregion


        #region 页面

        this.Page = new AntdUI.Panel()
        {
            Dock = DockStyle.Fill,
            Padding = new Padding(5),
        };

        spli.Panel2.Controls.Add(this.Page);
        #endregion


        //添加顶部功能内部组件
        panelMenuTop.Controls.Add(inputMenuSearch);
        panelMenuTop.Controls.Add(btnMenuCollapsed);
        panelMenu.Controls.Add(menu1);
        //添加菜单
        spli.Panel1.Controls.Add(panelMenu);
        //添加分割线
        spli.Panel1.Controls.Add(new Divider() { Dock = DockStyle.Top, Height = 5 });
        //添加菜单顶部功能
        spli.Panel1.Controls.Add(panelMenuTop);
        //添加整个布局
        this.Controls.Add(spli);

        this.SetMenuTabs(menu.GetUserMenuTagItems(), true);

        TabHeaderButton();

        //移动结束时候，记录位置
        spli.SplitterMoved += (s, e) =>
        {
            if (!menu1.Collapsed)
            {
                AppConfig.Config.MenuSplitterDistance = e.SplitX;
            }
        };


        menu1.SelectChanged += (s, e) =>
        {
            if (menuSelectMode == 0)
            {
                var item = e.Value;
                if (item?.Tag is MenuItemTag tag)
                {
                    LoadTabPage(tag.Code ?? "", item.Text ?? "", tag.Url, tag.PathText ?? "", item.IconSvg, tag.Closeable, tag.PageType);
                }
            }
        };

        tabHeader.TabChanged += (s, e) =>
        {
            if (tabPageSelectMode == 0)
            {
                var item = this.Items.FirstOrDefault<PageItem>(it => it.Text == e.Value.Text);
                if (item != null)
                {
                    string url = item.MenuUrl;
                    MenuCollapsedAll(null);
                    menuSelectMode = SelectMode.Custom;
                    SelectMenu(url, null);
                    menuSelectMode = 0;
                    menu1.Refresh();
                    item.Selected = true;
                }
            }
        };
        tabHeader.TabClosing += (s, e) =>
        {
            var item = this.Items.FirstOrDefault<PageItem>(it => it.Text == e.Value.Text);
            if (item != null)
            {
                this.Items.Remove(item);
                item.Dispose();
            }
        };


        //设置图标
        try
        {
            string exePath = System.Reflection.Assembly.GetEntryAssembly().Location;
            var image = Icon.ExtractAssociatedIcon(exePath).ToBitmap();
            this.tabHeader.Icon = image;
            this.Icon = image.ToIcon();
        }
        catch
        {
            var iconimage = ImageHelp.SvgToBmp("HomeOutlined");
            this.tabHeader.Icon = iconimage;
            this.Icon = iconimage.ToIcon();
        }

        this.Controls.Add(tabHeader);
    }


    private void TabHeaderButton()
    {
        #region 皮肤设置


        var btnTheme = new AntdUI.Button()
        {
            IconSvg = "MoonOutlined",
            Dock = DockStyle.Right,
            Size = new Size(40, 40),
            Ghost = true,
        };
        this.tabHeader.Controls.Add(btnTheme);

        AntdHelp.SetTheme(this, btnTheme);
        SetTabHeaderBackColor();
        btnTheme.Click += (s, e) =>
        {
            AntdHelp.SetTheme(this, btnTheme, !AntdUI.Config.IsDark, AppSettings.Get<Color>("ThemeColor"));
            SetTabHeaderBackColor();
        };
        #endregion

        #region 顶部设置按钮
        var steebutton = new AntdUI.Button()
        {
            IconSvg = "SettingOutlined",
            Dock = DockStyle.Right,
            Ghost = true,
            Width = 35,
        };
        steebutton.Click += (s, e) => new Settings.SettingsForm().ShowDialog();
        this.tabHeader.Controls.Add(steebutton);
        #endregion


        var userInfo = new UserInfo()
        {
            Dock = DockStyle.Right,
            Width = 100,
            IconSize = new Size(26, 26),
        };
        userInfo.MouseDown += (s, e) =>
        {
            var d = this.tabHeader.GetType().GetMethod("OnMouseDown", BindingFlags.NonPublic | BindingFlags.Instance);
            d?.Invoke(this.tabHeader, [e]);
        };
        this.tabHeader.Controls.Add(userInfo);

        if (identity.SysUser != null)
        {
            userInfo.DataBinding(identity, a => a.DisplayName, b => b.DisplayName);
            userInfo.Image = identity.Image;
        }
    }

    void SetTabHeaderBackColor()
    {
        if (AntdUI.Config.IsDark)
        {
            this.tabHeader.BackColor = Color.FromArgb(51, 51, 51);
        }
        else
        {
            this.tabHeader.BackColor = Color.FromArgb(232, 232, 232);
        }
    }


    SelectMode menuSelectMode = 0;



    public class PageItem : IDisposable
    {
        private bool selected;

        public string Name { get; set; }
        public string Text { get; set; }
        public string MenuUrl { get; set; }
        public string IconSvg { get; set; }
        public bool Closeable { get; set; } = true;
        public Control Control { get; set; }
        public bool Selected
        {
            get => selected;
            set
            {
                selected = value;
                owner?.Selected(this);
            }
        }
        public PageItemCollection owner { get; set; }
        public SysDefaultForm sysDefaultForm { get; set; }

        public event EventHandler? Disposed;
        public void Dispose()
        {
            Disposed?.Invoke(this, new EventArgs());
            this.Name = null;
            this.Text = null;
            this.MenuUrl = null;
            this.IconSvg = null;
            this.Closeable = false;
            this.Control.Dispose();
        }
    }

    public class PageItemCollection(SysDefaultForm owner) : Controls.ObjectCollection
    {
        protected override void OnInsert(int index, object? value)
        {
            base.OnInsert(index, value);
            if (value is PageItem item)
            {
                owner.tabHeader.Text = null;
                item.owner = this;
                item.sysDefaultForm = owner;
                owner.Page.Controls.Add(item.Control);
                owner.tabHeader.AddTab(item.Text, item.IconSvg);
            }
        }

        protected override void OnRemove(int index, object? value)
        {
            base.OnRemove(index, value);
            if (this.Count == 1)
            {
                owner.tabHeader.Text = owner.title;
            }
        }

        public void Selected(PageItem item)
        {
            foreach (PageItem p in this)
            {
                p.Control.Visible = false;
            }
            item.Control.Visible = true;
            owner.tabHeader.SelectedIndex = owner.tabHeader.Items.FindIndex(it => it.Text == item.Text);
        }
    }


    #region 私有方法


    /// <summary>
    /// 设置菜单
    /// </summary>
    private void SetMenuTabs(List<MenuTagItem> myMenuItems, bool showFirstPage = false)
    {
        this.SetMenu(myMenuItems);
        if (showFirstPage)
        {
            this.MenuSelectDefault();
        }
    }
    /// <summary>
    /// 选中指定菜单项
    /// </summary>
    /// <param name="url"></param>
    /// <param name="parent"></param>
    private void SelectMenu(string url, AntdUI.MenuItem? parent)
    {
        AntdUI.MenuItemCollection items;
        if (parent == null) items = menu1.Items;
        else items = parent.Sub;
        foreach (AntdUI.MenuItem item in items)
        {
            if (item.Tag is MenuItemTag tag)
            {
                if (tag.Path != null)
                {
                    if (string.Equals(tag.Url, url, StringComparison.OrdinalIgnoreCase))
                    {
                        menu1.Select(item, true);
                        item.Select = true;
                        MenuExpandAllParent(item);
                        menu1.Invalidate();
                    }
                    else
                    {
                        item.Select = false;
                    }
                }
            }
            if (item.Sub != null) SelectMenu(url, item);
        }
    }
    /// <summary>
    /// 菜单默认选中项
    /// </summary>
    public void MenuSelectDefault()
    {
        var item = menu1.Items
            .Where(it => it.Tag is MenuItemTag tag && (tag.Url == "/home" || tag.Url == "/" || tag.Url == "/index"))
            .FirstOrDefault();
        if (item?.Tag is MenuItemTag tag)
        {
            LoadTabPage(tag.Code ?? "", item.Text ?? "", tag.Url, tag.PathText ?? "", item.IconSvg, tag.Closeable, tag.PageType);
        }
    }

    /// <summary>
    /// 收缩所有菜单项
    /// </summary>
    /// <param name="parent"></param>
    private void MenuCollapsedAll(AntdUI.MenuItem? parent)
    {
        AntdUI.MenuItemCollection items;
        if (parent == null) items = menu1.Items;
        else items = parent.Sub;
        foreach (AntdUI.MenuItem item in items)
        {
            if (item.Expand) item.Expand = false;
            if (item.Sub != null) MenuCollapsedAll(item);
        }
    }

    /// <summary>
    /// 展开所有菜单项
    /// </summary>
    /// <param name="parent"></param>
    private void MenuExpandAll(AntdUI.MenuItem? parent)
    {
        AntdUI.MenuItemCollection items;
        if (parent == null) items = menu1.Items;
        else items = parent.Sub;
        foreach (AntdUI.MenuItem item in items)
        {
            if (item.CanExpand && !item.Expand) item.Expand = true;
            if (item.Sub != null) MenuExpandAll(item);
        }
    }


    /// <summary>
    /// 展开指定菜单项的所有上级菜单
    /// </summary>
    /// <param name="item"></param>
    private static void MenuExpandAllParent(AntdUI.MenuItem item)
    {
        if (item.Tag is MenuItemTag tag)
        {
            if (tag.Parent != null)
            {
                if (tag.Parent.CanExpand && !tag.Parent.Expand)
                {
                    tag.Parent.Expand = true;
                    // 选中上级菜单，当 Menu.Collapsed = true 时可以看到效果
                    tag.Parent.Select = true;
                }
                MenuExpandAllParent(tag.Parent);
            }
        }
    }

    /// <summary>
    /// 取消所有菜单项的选中状态
    /// </summary>
    /// <param name="parent"></param>
    private void UnSelectMenuAll(AntdUI.MenuItem? parent)
    {
        AntdUI.MenuItemCollection items;
        if (parent == null) items = menu1.Items;
        else items = parent.Sub;
        foreach (AntdUI.MenuItem item in items)
        {
            if (item.Select)
            {
                item.Select = false;
            }
            if (item.Sub != null) UnSelectMenuAll(item);
        }
    }

    /// <summary>
    /// 主菜单
    /// </summary>
    private List<MenuTagItem> _menus = [];
    private readonly HashSet<string> menuCodes = [];

    /// <summary>
    /// 创建菜单
    /// </summary>
    /// <param name="parent1"></param>
    /// <param name="parent2"></param>
    private void CreateMenu(MenuTagItem? parent1, AntdUI.MenuItem? parent2)
    {
        List<MenuTagItem> _menus;

        if (parent1 == null)
        {
            _menus = this._menus;
        }
        else
        {
            _menus = parent1.Sub;
        }

        foreach (MenuTagItem _item in _menus)
        {
            if (menuCodes.Contains(_item.Code))
            {
                throw new Exception($"菜单唯一编码（{_item.Code}）重复！");
            }
            else
            {
                menuCodes.Add(_item.Code);
            }

            AntdUI.MenuItem item = new(_item.Name)
            {
                IconSvg = _item.IconSvg,
                Tag = new MenuItemTag(_item.Code) { Closeable = _item.Closeable, Url = _item.Code ?? "", PageType = _item.PageType },
            };

            if (parent2 == null)
            {
                menu1.Items.Add(item);
            }
            else
            {
                parent2.Sub.Add(item);
            }

            if (_item.Sub.Count > 0) CreateMenu(_item, item);
        }
    }
    /// <summary>
    /// 设置所有菜单项的父级
    /// </summary>
    /// <param name="parent"></param>
    private void SetMenuItemParent(AntdUI.MenuItem? parent)
    {
        AntdUI.MenuItemCollection items;
        if (parent == null) items = menu1.Items;
        else items = parent.Sub;
        foreach (AntdUI.MenuItem item in items)
        {
            if (item.Tag is MenuItemTag tag)
            {
                tag.Parent = parent;
            }
            if (item.Sub != null) SetMenuItemParent(item);
        }
    }

    /// <summary>
    /// 设置所有菜单项的路径
    /// </summary>
    /// <param name="parent"></param>
    private void SetMenuItemPath(AntdUI.MenuItem? parent)
    {
        AntdUI.MenuItemCollection items;
        if (parent == null) items = menu1.Items;
        else items = parent.Sub;
        foreach (AntdUI.MenuItem item in items)
        {
            if (item.Tag is MenuItemTag tag)
            {
                if (parent == null)
                {
                    if (tag.Path == null)
                    {
                        tag.Path = $"/{tag.Code}";
                        tag.PathText = $"/{item.Text}";
                    }
                    else
                    {
                        tag.Path = $"/{tag.Code}";
                        tag.PathText = $"/{tag.PathText}";
                    }
                }
                else
                {
                    if (parent.Tag is MenuItemTag tag2)
                    {
                        if (tag.Path == null)
                        {
                            tag.Path = $"{tag2.Path}/{tag.Code}";
                            tag.PathText = $"{tag2.PathText}/{item.Text}";
                        }
                        else
                        {
                            tag.Path = $"{tag2.Path}/{tag.Path}";
                            tag.Path = $"{tag2.PathText}/{tag.PathText}";
                        }
                    }
                }
            }
            if (item.Sub != null) SetMenuItemPath(item);
        }
    }

    /// <summary>
    /// 设置菜单项
    /// </summary>
    /// <param name="menus"></param>
    public void SetMenu(List<MenuTagItem>? menus)
    {
        if (menus != null) _menus = menus;
        menu1.Items.Clear();
        menuCodes.Clear();
        CreateMenu(null, null);
        MenuCollapsedAll(null);
        SetMenuItemParent(null);
        SetMenuItemPath(null);
    }


    /// <summary>
    /// 获取地址匹配指定菜单项
    /// </summary>
    /// <param name="url"></param>
    /// <param name="menuItem"></param>
    /// <returns></returns>
    private AntdUI.MenuItem? GetMenuItem(string url, AntdUI.MenuItem? menuItem = null)
    {
        var items = menuItem == null ? menu1.Items : menuItem.Sub;
        foreach (var item in items)
        {
            if (item.Tag is MenuItemTag tag)
            {
                if (string.Equals(tag.Url, url, StringComparison.OrdinalIgnoreCase))
                {
                    return item;
                }
            }
            if (item.Sub != null)
            {
                var subItem = GetMenuItem(url, item);
                if (subItem != null) return subItem;
            }
        }
        return null;
    }


    /// <summary>
    /// MenuItem 自定义数据模型
    /// </summary>
    /// <param name="code"></param>
    class MenuItemTag(string code)
    {
        /// <summary>
        /// 菜单项唯一编码
        /// </summary>
        public string Code { get; set; } = code;
        /// <summary>
        /// 菜单项路径
        /// </summary>
        public string? Path { get; set; }
        /// <summary>
        /// 菜单项地址
        /// </summary>
        public string? Url { get; set; }
        /// <summary>
        /// 菜单项路径文本
        /// </summary>
        public string? PathText { get; set; }
        /// <summary>
        /// 父级菜单项
        /// </summary>
        public AntdUI.MenuItem? Parent { get; set; }

        /// <summary>
        /// 是否允许关闭页面
        /// </summary>
        public bool Closeable { get; set; } = true;
        public Type? PageType { get; set; }
    }


    private enum SelectMode
    {
        Default = 0,
        Custom = 1,
    }
    private SelectMode tabPageSelectMode;

    /// <summary>
    /// 加载页面
    /// </summary>
    /// <param name="code"></param>
    /// <param name="title"></param>
    /// <param name="url"></param>
    /// <param name="pathText"></param>
    /// <param name="svg"></param>
    /// <param name="closeable"></param>
    private void LoadTabPage(string code, string title, string? url, string pathText, string? svg, bool closeable, Type? pageType)
    {
        tabPageSelectMode = SelectMode.Custom;

        bool findInstance = false;

        foreach (PageItem item in Items)
        {
            if (string.Equals(item.MenuUrl, url, StringComparison.OrdinalIgnoreCase))
            {
                item.Selected = true;
                findInstance = true;
                break;
            }
        }

        if (!findInstance)
        {
            var page = new PageItem()
            {
                Text = title,
                IconSvg = svg,
                Closeable = closeable,
                MenuUrl = url,
            };
            //if (!closeable)
            //{
            //    page.ReadOnly = true;
            //}
            page.Disposed += (s, e) =>
            {
                if (ParentForm != null)
                {
                    AntdUI.Message.info(ParentForm, $"页面【{page.Text}】已关闭。");
                }
            };


            //AntdUI.Panel panel = new()
            //{
            //    Dock = DockStyle.Fill,
            //    Padding = new(2),
            //};
            //page.Controls.Add(panel);


            try
            {
                Control pageContent;
                try
                {
                    object[] args = [title, url, pathText];
                    pageContent = App.GetControlService(pageType) ?? (Control)Activator.CreateInstance(pageType, args)!;
                }
                catch
                {
                    try
                    {
                        pageContent = (UserControl)Activator.CreateInstance(pageType)!;
                    }
                    catch
                    {
                        return;
                    }
                }
                pageContent.Dock = DockStyle.Fill;
                //检查属性是否存在 PageCode 若是存在设置值 反射方式赋值
                pageContent.GetType().GetProperty("PageCode")?.SetValue(pageContent, code);
                if (Parent is AntdUI.BaseForm form) form.AutoDpi(pageContent);
                page.Control = pageContent;
            }
            catch (Exception ex)
            {
                var alert = new AntdUI.Alert()
                {
                    TextTitle = "警告",
                    Text = ex.Message,
                    Icon = AntdUI.TType.Warn,
                    Height = 100,
                    Dock = DockStyle.Top,
                    Padding = new Padding(10)
                };
                //panel.Padding = new(10);
                //panel.Controls.Add(alert);
                page.Control = alert;
            }
            //tabs1.Pages.Add(page);
            //tabs1.SelectedTab = page;
            this.Items.Add(page);
            page.Selected = true;
        }

        tabPageSelectMode = 0;
    }

    #endregion

}
